/* Code licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php */
/**
* @description <p>Lister singleton widget to list and edit inline PhoneBook entries.</p>
* @requires PhoneBook, ANVIL, YAHOO
**/

/*
    ISSUE: Many or most of the properties and methods could be reduced to a reusable widget object, 
    but for now, it is simple and interesting to first make LISTER a singleton.
*/    

if (typeof LISTER == "undefined") {
    var LISTER = {};
}

// -- configuration data -- 

// Static data for low-level testing    
LISTER.localData = { 
    "result" : [['c5b6bbb1-66d6-49cb-9db6-743af6627828', 'Clinton', 'William', '555-743-7828', 'bubba', '08/19/1992', 37.5, '0'],
    ['7c424227-8e19-4fb5-b089-423cfca723e1', 'Roosevelt', 'Theodore', '555-743-8942', 'bull', '09/14/2002', 37.5, '0'],
    ['9320ea40-0c01-43e8-9cec-8fb9b3928c2c', 'Kennedy', 'John F.', '555-743-3928', 'fitz', '05/29/1987', 37.5, '0'],
    ['3b27c933-c1dc-4d85-9744-c7d9debae196', 'Pierce', 'Franklin', '555-743-7919', 'benji', '11/18/1984', 35, '0'],
    ['554ff9e7-a6f5-478a-b76b-a666f5c54e40', 'Jefferson', 'Thomas', '555-743-5440', 'monty', '07/04/1976', 37.5, '0']]
};

// -- helper functions --

// Present an X if client is an editor
LISTER.editorFormatter = function (elCell, oRecord, oColumn, oData) {
    if(oRecord["editor"]=="1") {
        elCell.innerHTML = "X"; // ISSUE: Carries over to corresponding cell if table is paginated
    }
};

LISTER.refresh = function (data) {
    var lister = LISTER.getDataTable();
    if (lister===null) {
        // initialization failed
        LISTER.init();
    }
    else {
       var rs = lister.getRecordSet();
       var rows = rs.replace(data.result);      
       lister.replaceRows(rows);        
    }    
};

LISTER.getSelectedRecord = function () {
    var lister = LISTER.getDataTable(); // this?
    var rs = lister.getRecordSet();
    var row = lister.getSelectedRecordIds(); 
    if (row.length===0) {
        lister.getRow(0); // No row was selected
        row = lister.getSelectedRecordIds(); 
    }
    var record = rs.getRecord(row[row.length-1]); // ISSUE: Returns row selected on each page
    return record;
};

// -- handlers and callbacks --- 

LISTER.onRefresh_load = function (data) {
    LISTER.refresh(data);
    LISTER.scrollToTop();       
    var message = "Refreshed entries";
    ANVIL.setMessage(message);        
};

LISTER.onRefresh = function (p_oEvent) {
    PhoneBook.rpc.entry_list(LISTER.onRefresh_load).call(ANVIL.channel);                
};      

// inline edit events (as opposed to form editor)               
LISTER.onEditCell = function (oArgs) {
    ANVIL.setMessage("Enter to save; Escape to cancel");
};

LISTER.onCancelEditCell = function (oArgs) {
    ANVIL.clearMessage();
};

LISTER.onRecordSetUpdate = function (oArgs) {        
    var values = oArgs.record;        
    if (values.entry_key)
        PhoneBook.rpc.entry_save(values,EDITOR.onSaveUpdate_load).call(ANVIL.channel);
    else
        PhoneBook.rpc.entry_save(values,EDITOR.onSaveInsert_load).call(ANVIL.channel);
};   

// See Issue 18
LISTER.onDeleteRefresh_load  = function (data) {
    LISTER.refresh(data);
    LISTER.scrollToTop(); // ISSUE: Seek best available row
    var message = "Deleted entry and refreshed list";
    ANVIL.setMessage(message);        
};

LISTER.onDelete_load =  function (data) {
    ANVIL.setMessage("Deleted: " + data.result.user_name); 
    PhoneBook.rpc.entry_list(EDITOR.onDeleteRefresh_load).call(ANVIL.channel);           
};

LISTER.onRecordSetDelete = function(oArgs) {            
    var values = oArgs.record;
    var entry_key = values.entry_key;
    LISTER.deleteConfirm(entry_key);
};  

// Content menu (right-click)
LISTER.onContextMenuClick = function(p_sType, p_aArgs, p_oMenu) {
  var task = p_aArgs[1];
  if(task) {
    // Extract which row was context-clicked
     var row = this.contextEventTarget;
       while(row.tagName.toLowerCase() != "tr") {
          row = row.parentNode;
          if(row.tagName.toLowerCase == "body") {
              row = null;
              break;
          }
      }                
      if(row) {
          switch(task.index) {
              case 0: // Delete is first (and only) item
                  ANVIL.setMessage("Deleting item: " + row.cells[2].innerHTML);
                  lister.deleteRow(row); // YUI method
                  break;
               default:
                break;
          }
      }
  }
};                  

LISTER.onListerDelete = function(p_oEvent) {    
    var record = LISTER.getSelectedRecord();
    LISTER.deleteConfirm(record);
    LISTER.activate();        
};

LISTER.onEdit = function(p_oEvent) {       
    var record = LISTER.getSelectedRecord();
    if (record) { 
        var entry_key = record.entry_key;
        PhoneBook.rpc.entry(entry_key,EDITOR.onEdit_load).call(ANVIL.channel);
    }
    else {
        MENU.WorkflowHint();
    }
};


// --- API functions ---

LISTER.datatable_field; // DataTable widget

LISTER.dataTable = function (oDataTable) {
    if (arguments.length>0) {
        LISTER.datatable_field = oDataTable;
    }
    return LISTER.datatable_field;
};

LISTER.setDataTable = LISTER.dataTable;
LISTER.getDataTable = LISTER.dataTable;

LISTER.listerActivateEvent = new YAHOO.util.CustomEvent("listerActivateEvent",LISTER);

LISTER.deleteConfirm = function (values) {
    if ((values) && (values.user_name)) {
        var message = "Delete " + values.user_name + "?";
        if (confirm(message)) {
            PhoneBook.rpc.entry_delete(values.entry_key,EDITOR.onDelete_load).call(ANVIL.channel);
        }
    } else {
        MENU.WorkflowHint();   
    }
};   

LISTER.scrollToTop = function () {
    var lister = LISTER.getDataTable();
    lister.paginateRows();
    lister.showPage(0);
    lister.select(lister.getRow(0));        
};       

LISTER.scrollToEnd = function () {
    var lister = LISTER.getDataTable();
    lister.paginateRows();
    lister.showPage(lister._totalPages);
    lister.select(lister.getRow(0));
};       

// Initialize entry table
LISTER.load = function (data) {

    // Sort by last name and then first name
    var sortLastNameAsc = function (a, b) {
        var compFnc = YAHOO.util.Sort.compareAsc;
        var comp = compFnc(a.last_name, b.last_name);
        return (comp !== 0) ? comp : compFnc(a.first_name, b.first_name);
    };    
    var sortLastNameDesc = function (a, b) {
        var compFnc = YAHOO.util.Sort.compareDesc;
        var comp = compFnc(a.last_name, b.last_name);
        return (comp !== 0) ? comp : compFnc(a.first_name, b.first_name);
    };

    // column setup for lister
    var columnSetData = [
        {key:"last_name", text:"Last Name", sortable:true, resizeable:true, editor:"textbox",  
            sortOptions:{ascFunction:sortLastNameAsc,descFunction:sortLastNameDesc}},
        {key:"first_name", text:"First Name", sortable:true, resizeable:true, editor:"textbox"},
        {key:"extension", text:"Telephone", sortable:true, resizeable:true, editor:"textbox"},
        {key:"user_name", text:"User", sortable:true, resizeable:true, editor:"textbox"},
        {key:"hired", text:"Hired", sortable:true, resizeable:true, editor:"textbox"},
        {key:"hours", text: "Hours", type:"number", sortable:true, resizeable:true, editor:"textbox"}
    ];
    var columnSet = new YAHOO.widget.ColumnSet(columnSetData);

    // optional features
    var options = {
        caption: "YUI PhoneBook", 
        summary: "List of matching phonebook entries",
        rowsPerPage: 2, 
        rowsPerPageDropdown: [2,20,200],                  
        rowSingleSelect: true                
    };

    // record datasource
    var dataSource = new YAHOO.util.DataSource(data.result);
        dataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;            
        dataSource.responseSchema = {
            fields: ["entry_key","first_name","last_name","extension","user_name","hired","hours","editor"]
    };    

    // instantiate lister
    var lister = new YAHOO.widget.DataTable("listerTable", columnSet, dataSource, options);
    LISTER.setDataTable(lister);

    // subscribe highlight events
    lister.subscribe("cellMouseoutEvent",lister.onEventUnhighlightCell);
    lister.subscribe("cellMouseoverEvent",lister.onEventHighlightCell);                        
    lister.subscribe("cellClickEvent",lister.onEventSelectRow); // YUI handler
    
    // subscribe row select events
    lister.subscribe("selectEvent",MENU.onListerRowSelected); // our handler
    lister.subscribe("unselectEvent",MENU.onListerRowUnselected); // our handler
    lister.subscribe("listerActivateEvent",MENU.onListerRowUnselected); // our handler
    lister.select(lister.getRow(0));

    // subscribe update events
    lister.subscribe("cellDoubleclickEvent", lister.onEventEditCell); // YUI handler
    lister.subscribe("cellDoubleclickEvent", LISTER.onEditCell); // YUI handler
    lister.subscribe("recordSetUpdateEvent", LISTER.onRecordSetUpdate); // Our handler
    lister.subscribe("cellCancelEvent", LISTER.onCancelEditCell); // Our YUI handler

    // subscribe delete menu               
    var contextMenu = new YAHOO.widget.ContextMenu("contextMenu", 
        { trigger: lister.getBody() } );
    contextMenu.addItem("Delete Item");
    contextMenu.render(document.body);
    contextMenu.clickEvent.subscribe(LISTER.onContextMenuClick);
    lister.subscribe("recordSetDeleteEvent", LISTER.onRecordSetDelete); // Our handler   

};  

LISTER.init = function (data)  {
    PhoneBook.rpc.entry_list(LISTER.load).call(ANVIL.channel); // live database
    // LISTER.load(LISTER.localData); // static data
};   

LISTER.onProfileReady = function (e) {
    if (!MENU.isEditor) {
        lister.remove("cellDoubleclickEvent", lister.onEventEditCell); // YUI handler
        lister.remove("cellDoubleclickEvent", LISTER.onEditCell); // YUI handler
    }
}


// -- event bindings -- 

MENU.refreshEvent.subscribe(LISTER.onRefresh, MENU); 
MENU.editEvent.subscribe(LISTER.onEdit, MENU); 
MENU.listerDeleteEvent.subscribe(LISTER.onListerDelete, MENU); 
YAHOO.util.Event.onAvailable("listerTable", LISTER.init); // This is the div containing the widget

if (typeof PROFILE != "undefined") {
    PROFILE.profileReadyEvent.subscribe(LISTER.onProfileReady, LISTER); 
}




